import { createStep, createWorkflow } from '@mastra/core/workflows';
import { z } from 'zod';
import { generateCase } from '../agents/case-generator.agent';
import { chatWithSuspect } from '../agents/suspect.agent';
import {
  CaseData,
  SuspectData,
  ClueData,
  GameState,
  DeductionSubmission,
  CaseGenerationRequestSchema,
  SuspectDialogueRequestSchema,
  DeductionSubmissionSchema
} from '../types/game';

/**
 * 调查工作流输入结构
 */
const InvestigationInputSchema = z.object({
  action: z.enum(['start_case', 'chat_suspect', 'submit_deduction', 'get_status']),
  caseGenerationRequest: CaseGenerationRequestSchema.optional(),
  suspectDialogueRequest: SuspectDialogueRequestSchema.optional(),
  deductionSubmission: DeductionSubmissionSchema.optional(),
  gameId: z.string().optional(),
});

/**
 * 调查工作流输出结构
 */
const InvestigationOutputSchema = z.object({
  success: z.boolean(),
  message: z.string(),
  data: z.any().optional(),
  gameState: z.object({
    caseId: z.string(),
    phase: z.enum(['investigation', 'deduction', 'result']),
    timeRemaining: z.number(),
    discoveredClues: z.array(z.string()),
    conversationCount: z.number(),
    suspectInteractions: z.record(z.number()),
    score: z.number(),
  }).optional(),
});

/**
 * 游戏状态存储（实际应用中应该使用数据库）
 */
const gameStates = new Map<string, {
  case: CaseData;
  suspects: SuspectData[];
  clues: ClueData[];
  gameState: GameState;
  conversations: any[];
}>();

/**
 * 开始新案件的步骤
 */
const startCaseStep = createStep({
  id: 'start-case',
  description: '生成新的推理案件并初始化游戏状态',
  inputSchema: z.object({
    caseGenerationRequest: CaseGenerationRequestSchema,
    gameId: z.string(),
  }),
  outputSchema: z.object({
    success: z.boolean(),
    message: z.string(),
    caseData: z.any(),
    gameState: z.any(),
  }),
  execute: async ({ inputData }) => {
    try {
      const { caseGenerationRequest, gameId } = inputData;
      
      console.log(`开始生成案件，游戏ID: ${gameId}`);
      
      // 生成案件数据
      const caseData = await generateCase(
        caseGenerationRequest.difficulty,
        caseGenerationRequest.theme,
        caseGenerationRequest.suspectCount
      );
      
      if (!caseData || !caseData.case) {
        throw new Error('案件生成失败');
      }
      
      // 初始化游戏状态
      const gameState: GameState = {
        caseId: caseData.case.id,
        phase: 'investigation',
        timeRemaining: caseGenerationRequest.difficulty === 'easy' ? 15 : 
                      caseGenerationRequest.difficulty === 'normal' ? 12 : 10,
        discoveredClues: caseData.initialClues
          .filter((clue: any) => clue.isRevealed)
          .map((clue: any) => clue.id),
        conversationCount: 0,
        suspectInteractions: {},
        score: 0,
      };
      
      // 初始化嫌疑人互动计数
      caseData.suspects.forEach((suspect: any) => {
        gameState.suspectInteractions[suspect.id] = 0;
      });
      
      // 存储游戏状态
      gameStates.set(gameId, {
        case: caseData.case,
        suspects: caseData.suspects,
        clues: caseData.initialClues,
        gameState,
        conversations: []
      });
      
      console.log(`案件生成成功: ${caseData.case.title}`);
      
      return {
        success: true,
        message: '案件生成成功',
        caseData: {
          case: caseData.case,
          suspects: caseData.suspects.map((suspect: any) => ({
            ...suspect,
            secrets: undefined, // 不向前端暴露秘密
            isCulprit: undefined, // 不向前端暴露真凶身份
          })),
          revealedClues: caseData.initialClues.filter((clue: any) => clue.isRevealed)
        },
        gameState
      };
      
    } catch (error) {
      console.error('开始案件失败:', error);
      return {
        success: false,
        message: `案件生成失败: ${error instanceof Error ? error.message : '未知错误'}`,
        caseData: null,
        gameState: null
      };
    }
  },
});

/**
 * 与嫌疑人对话的步骤
 */
const chatSuspectStep = createStep({
  id: 'chat-suspect',
  description: '处理侦探与嫌疑人的对话',
  inputSchema: z.object({
    suspectDialogueRequest: SuspectDialogueRequestSchema,
    gameId: z.string(),
  }),
  outputSchema: z.object({
    success: z.boolean(),
    message: z.string(),
    response: z.any(),
    gameState: z.any(),
  }),
  execute: async ({ inputData }) => {
    try {
      const { suspectDialogueRequest, gameId } = inputData;
      const gameData = gameStates.get(gameId);
      
      if (!gameData) {
        throw new Error('游戏状态不存在');
      }
      
      if (gameData.gameState.phase !== 'investigation') {
        throw new Error('当前不在调查阶段');
      }
      
      // 查找嫌疑人
      const suspect = gameData.suspects.find(s => s.id === suspectDialogueRequest.suspectId);
      if (!suspect) {
        throw new Error('嫌疑人不存在');
      }
      
      console.log(`与嫌疑人 ${suspect.name} 对话: ${suspectDialogueRequest.question}`);
      
      // 获取对话历史
      const conversationHistory = gameData.conversations
        .filter(conv => conv.suspectId === suspectDialogueRequest.suspectId)
        .flatMap(conv => conv.messages);
      
      // 调用嫌疑人Agent进行对话
      const response = await chatWithSuspect(
        suspect,
        suspectDialogueRequest.question,
        conversationHistory,
        gameData.gameState.timeRemaining,
        gameData.gameState.discoveredClues
      );
      
      // 更新对话记录
      const conversationId = `conv-${Date.now()}`;
      const newConversation = {
        id: conversationId,
        caseId: gameData.case.id,
        suspectId: suspect.id,
        messages: [
          {
            role: 'detective' as const,
            content: suspectDialogueRequest.question,
            timestamp: new Date().toISOString(),
          },
          {
            role: 'suspect' as const,
            content: response.content,
            timestamp: new Date().toISOString(),
            emotion: response.emotion,
          }
        ],
        cluesDiscovered: response.newClues.map(clue => clue.id),
        suspicionChange: response.suspicionLevel - suspect.suspicionLevel,
      };
      
      gameData.conversations.push(newConversation);
      
      // 更新嫌疑人状态
      suspect.suspicionLevel = response.suspicionLevel;
      suspect.emotionalState = response.emotion;
      
      // 更新游戏状态
      gameData.gameState.conversationCount++;
      gameData.gameState.suspectInteractions[suspect.id]++;
      gameData.gameState.timeRemaining = Math.max(0, gameData.gameState.timeRemaining - 1);
      
      // 添加新发现的线索
      response.newClues.forEach(newClue => {
        if (!gameData.gameState.discoveredClues.includes(newClue.id)) {
          gameData.gameState.discoveredClues.push(newClue.id);
          gameData.clues.push(newClue);
          gameData.gameState.score += newClue.importance * 10;
        }
      });
      
      // 检查是否时间用完
      if (gameData.gameState.timeRemaining <= 0) {
        gameData.gameState.phase = 'deduction';
      }
      
      console.log(`对话完成，新线索数量: ${response.newClues.length}`);
      
      return {
        success: true,
        message: '对话成功',
        response: {
          content: response.content,
          emotion: response.emotion,
          suspicionLevel: response.suspicionLevel,
          newClues: response.newClues,
          hints: response.hints
        },
        gameState: gameData.gameState
      };
      
    } catch (error) {
      console.error('对话失败:', error);
      return {
        success: false,
        message: `对话失败: ${error instanceof Error ? error.message : '未知错误'}`,
        response: null,
        gameState: null
      };
    }
  },
});

/**
 * 提交推理结果的步骤
 */
const submitDeductionStep = createStep({
  id: 'submit-deduction',
  description: '处理侦探的推理结果提交',
  inputSchema: z.object({
    deductionSubmission: DeductionSubmissionSchema,
    gameId: z.string(),
  }),
  outputSchema: z.object({
    success: z.boolean(),
    message: z.string(),
    result: z.any(),
    gameState: z.any(),
  }),
  execute: async ({ inputData }) => {
    try {
      const { deductionSubmission, gameId } = inputData;
      const gameData = gameStates.get(gameId);
      
      if (!gameData) {
        throw new Error('游戏状态不存在');
      }
      
      if (gameData.gameState.phase !== 'deduction') {
        throw new Error('当前不在推理阶段');
      }
      
      console.log(`提交推理结果，指控嫌疑人: ${deductionSubmission.accusedSuspectId}`);
      
      // 查找被指控的嫌疑人
      const accusedSuspect = gameData.suspects.find(s => s.id === deductionSubmission.accusedSuspectId);
      if (!accusedSuspect) {
        throw new Error('被指控的嫌疑人不存在');
      }
      
      // 查找真凶
      const realCulprit = gameData.suspects.find(s => s.isCulprit);
      if (!realCulprit) {
        throw new Error('案件数据错误：找不到真凶');
      }
      
      // 判断推理是否正确
      const isCorrect = accusedSuspect.id === realCulprit.id;
      
      // 计算得分
      let finalScore = gameData.gameState.score;
      
      if (isCorrect) {
        // 正确推理的奖励分数
        finalScore += 1000;
        // 根据剩余时间给予奖励
        finalScore += gameData.gameState.timeRemaining * 50;
        // 根据推理信心给予奖励
        finalScore += deductionSubmission.confidence * 10;
      } else {
        // 错误推理的惩罚
        finalScore = Math.max(0, finalScore - 500);
      }
      
      // 更新游戏状态
      gameData.gameState.phase = 'result';
      gameData.gameState.score = finalScore;
      
      // 生成结果数据
      const result = {
        isCorrect,
        accusedSuspect: {
          id: accusedSuspect.id,
          name: accusedSuspect.name,
        },
        realCulprit: {
          id: realCulprit.id,
          name: realCulprit.name,
        },
        reasoning: deductionSubmission.reasoning,
        evidenceUsed: deductionSubmission.evidenceUsed,
        confidence: deductionSubmission.confidence,
        finalScore,
        caseTitle: gameData.case.title,
        caseSolution: {
          motive: gameData.case.motive,
          method: gameData.case.murderWeapon,
          opportunity: realCulprit.alibi + ' (实际上是伪造的)',
        },
        discoveredClues: gameData.clues.filter(clue => 
          gameData.gameState.discoveredClues.includes(clue.id)
        ),
        totalClues: gameData.clues.length,
        conversationCount: gameData.gameState.conversationCount,
      };
      
      console.log(`推理结果: ${isCorrect ? '正确' : '错误'}，最终得分: ${finalScore}`);
      
      return {
        success: true,
        message: isCorrect ? '推理正确！' : '推理错误！',
        result,
        gameState: gameData.gameState
      };
      
    } catch (error) {
      console.error('提交推理失败:', error);
      return {
        success: false,
        message: `提交推理失败: ${error instanceof Error ? error.message : '未知错误'}`,
        result: null,
        gameState: null
      };
    }
  },
});

/**
 * 获取游戏状态的步骤
 */
const getStatusStep = createStep({
  id: 'get-status',
  description: '获取当前游戏状态',
  inputSchema: z.object({
    gameId: z.string(),
  }),
  outputSchema: z.object({
    success: z.boolean(),
    message: z.string(),
    gameState: z.any(),
    gameData: z.any(),
  }),
  execute: async ({ inputData }) => {
    try {
      const { gameId } = inputData;
      const gameData = gameStates.get(gameId);
      
      if (!gameData) {
        throw new Error('游戏状态不存在');
      }
      
      // 返回游戏状态和相关数据（不包含敏感信息）
      const safeGameData = {
        case: {
          ...gameData.case,
          culpritId: undefined, // 不暴露真凶ID
        },
        suspects: gameData.suspects.map(suspect => ({
          ...suspect,
          secrets: undefined, // 不暴露秘密
          isCulprit: undefined, // 不暴露真凶身份
        })),
        discoveredClues: gameData.clues.filter(clue => 
          gameData.gameState.discoveredClues.includes(clue.id)
        ),
        conversations: gameData.conversations.map(conv => ({
          ...conv,
          // 只返回最近的几条对话
          messages: conv.messages.slice(-10)
        })),
      };
      
      return {
        success: true,
        message: '获取状态成功',
        gameState: gameData.gameState,
        gameData: safeGameData
      };
      
    } catch (error) {
      console.error('获取状态失败:', error);
      return {
        success: false,
        message: `获取状态失败: ${error instanceof Error ? error.message : '未知错误'}`,
        gameState: null,
        gameData: null
      };
    }
  },
});

/**
 * 调查工作流主流程
 */
const investigationWorkflow = createWorkflow({
  id: 'investigation-workflow',
  inputSchema: InvestigationInputSchema,
  outputSchema: InvestigationOutputSchema,
})
  .then(async ({ inputData }) => {
    const { action, gameId = `game-${Date.now()}` } = inputData;
    
    console.log(`执行调查工作流，动作: ${action}，游戏ID: ${gameId}`);
    
    switch (action) {
      case 'start_case':
        if (!inputData.caseGenerationRequest) {
          throw new Error('缺少案件生成请求参数');
        }
        return await startCaseStep.execute({
          inputData: {
            caseGenerationRequest: inputData.caseGenerationRequest,
            gameId
          }
        });
        
      case 'chat_suspect':
        if (!inputData.suspectDialogueRequest) {
          throw new Error('缺少嫌疑人对话请求参数');
        }
        return await chatSuspectStep.execute({
          inputData: {
            suspectDialogueRequest: inputData.suspectDialogueRequest,
            gameId
          }
        });
        
      case 'submit_deduction':
        if (!inputData.deductionSubmission) {
          throw new Error('缺少推理提交参数');
        }
        return await submitDeductionStep.execute({
          inputData: {
            deductionSubmission: inputData.deductionSubmission,
            gameId
          }
        });
        
      case 'get_status':
        return await getStatusStep.execute({
          inputData: { gameId }
        });
        
      default:
        throw new Error(`未知的动作类型: ${action}`);
    }
  });

// 提交工作流
investigationWorkflow.commit();

/**
 * 导出工作流和相关函数
 */
export { investigationWorkflow };

/**
 * 清理游戏状态（用于测试或重置）
 * @param gameId 游戏ID
 */
export function clearGameState(gameId: string) {
  gameStates.delete(gameId);
  console.log(`已清理游戏状态: ${gameId}`);
}

/**
 * 获取所有活跃的游戏ID
 * @returns 游戏ID列表
 */
export function getActiveGameIds(): string[] {
  return Array.from(gameStates.keys());
}

/**
 * 获取游戏统计信息
 * @param gameId 游戏ID
 * @returns 统计信息
 */
export function getGameStatistics(gameId: string) {
  const gameData = gameStates.get(gameId);
  if (!gameData) {
    return null;
  }
  
  return {
    caseTitle: gameData.case.title,
    difficulty: gameData.case.difficulty,
    suspectCount: gameData.suspects.length,
    totalClues: gameData.clues.length,
    discoveredClues: gameData.gameState.discoveredClues.length,
    conversationCount: gameData.gameState.conversationCount,
    timeRemaining: gameData.gameState.timeRemaining,
    currentScore: gameData.gameState.score,
    phase: gameData.gameState.phase,
    suspectInteractions: gameData.gameState.suspectInteractions,
  };
}